<?php
// *****************************************************************************
// Функции управления модулями
// Префикс mst_
// Автор: Алексей Дьяченко
// Автор: Лазарев Иван
// Библиотека распространяется по лицензии GPL
// Принять участие в разработке или скачать новую версию вы можете на сайте
// http://www.my-site.ru/
/*
	Copyright 2005-2007 Alex Djachenko http://www.my-site.ru
	Authors: Alex Djachenko, Ivan Lazarev
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/
// *****************************************************************************

// $MT_mod_type='lib';
// $MT_mod_name='my-site';
// $MT_mod_ver=20061006;
// $MT_mod_globals='';
$MT_core_ver=200708150;

// ************************************
// Работа с переменными
// ************************************
function mst_getcorever()
{
	global $MT_core_ver;
	return $MT_core_ver;
}

/**
 * @return Параметр(ы)
 * @param имя_параметра $name
 * @desc Получение опции из настроек сайта по имени или всего $MT_core_cfg, если имя не задано
*/
function mst_getconfig($name)
{   // Получить опцию из настроек сайта
    global $MT_core_cfg;
    if (empty($name))
    {
        return $MT_core_cfg;
    }
    else
    {
        return @$MT_core_cfg[$name];
    }
}
function mst_setthemes($theme)
{   // Получить опцию из настроек сайта
    global $MT_core_cfg;
	if (mst_util_checkmodname($theme))
	{
		// Имя темы правильное
		$MT_core_cfg['themes']=$theme;
	}else
	{
		//
		mst_error('Неправильное имя темы',"Имя темы {$theme} не корректно");
		
	}
	
    return $MT_core_cfg['themes'];
}
/**
 * @return путь
 * @param имя_параметра $name
 * @desc Возвращает путь из настроек сайта по ключу или всю $MT_core_path
*/
function mst_getpath($name)
{   // Получить путь из настроек сайта
    global $MT_core_path;
    if (empty($name))
    {
        return $MT_core_path;
    }
    else
    {
        return $MT_core_path[$name];
    }
}
/**
 * @return URL
 * @param имя_параметра $name
 * @desc Возвращает URL из настроек сайта по ключу или всю $MT_core_wwwpath
*/
function mst_getwwwpath($name)
{   // Получить URL из настроек сайта
    global $MT_core_wwwpath;
    if (empty($name))
    {
        return $MT_core_wwwpath;
    }
    else
    {
        return $MT_core_wwwpath[$name];
    }
}
function mst_getrunvars($name)
{   // Получить переменную из параметров точки входа
    global $MT_run;
    if (empty($name))
    {
        return $MT_run;
    }
    else
    {
        return @$MT_run[$name];
    }
}
function mst_gettimefromstart($round=null)
{
    global $MT_core_timestart;
    $time = microtime(true) - $MT_core_timestart;
    if (!is_null($round))
    {
        $time = round($time,$round);
    }
    return $time;
}

// ************************************
// Работа с путями и URL
// ************************************
/**
 * @return URL
 * @param mst-путь $filename
 * @param массив_доп_переменных $url_vars
 * @desc Возаращает URL по mst-пути и дополнительным параметрам.
*/
function mst_url($filename=null,$url_vars=NULL)
{   // Возвращает URL
    return mst_modurl(null,$filename,$url_vars);
}
/**
 * @return путь
 * @param имя_модуля $MT_mod_name
 * @param путь_внутри_модуля $filename
 * @param не генерировать ошибок $non_error
 * @param разрешить возвращение пути к несуществующим файлам  $non_exists
 * @desc Возвращает физический путь к модулю или файлу модуля
*/
function mst_modpath($MT_mod_name,$filename=null,$non_error=FALSE,$non_exists=false)
{   // Возвращает путь к модулю
	if (!mst_pvt_modtestexec($MT_mod_name,$filename,false,false))
	{  // Модуль вызван с неправильными параметрами
	    return false;
	}
    return mst_pvt_modpath($MT_mod_name,$filename,$non_error,$non_exists);
}
/**
 * @return URL
 * @param не_используется $MT_mod_name
 * @param mst-путь $filename
 * @param массив_доп_переменных $url_vars
 * @desc Возвращает URL по mst-пути и дополнительным параметрам
*/
function mst_modurl($MT_mod_name=null,$filename=null,$url_vars=NULL)
{   // Возвращает URL

    $filename_array=explode('/',$filename);
    $filename_cut=implode('/',array_slice($filename_array,1));
    if('THEMES'==$filename_array[0])
    {   // Запрошен url в теме
        // Проверяем, правильно ли переданы параметры
        if (is_null($MT_mod_name))
		{
			//
			$MT_mod_url_file=mst_getwwwpath('themes').mst_getconfig('themes').
                        "/".$filename_cut;
		}else
		{
			if (!mst_pvt_modtestexec($MT_mod_name))
			{
				// Имя модуля не передано или передано неправильно
				return false;
			}
			$MT_mod_url_file=mst_getwwwpath('themes').mst_getconfig('themes').
                        "/{$MT_mod_name}/".$filename_cut;
		}
        
        $MT_mod_url_file=mst_util_addurlvar($MT_mod_url_file,$url_vars);
    }elseif('SHELL'==$filename_array[0])
    {   // Запрошен url в одном из shell
        $MT_mod_url_file=mst_pvt_shellurl($filename_array[1],
                implode('/',array_slice($filename_array,2)),$url_vars);

    }elseif('CSHELL'==$filename_array[0])
    {   // Запрошен url в текущем shell
        $MT_mod_url_file=mst_pvt_shellurl(mst_getrunvars('shell'), $filename_cut,$url_vars);
    }elseif('THIS'==$filename_array[0])
    {   // Запрошен url текущей страницы
        $MT_mod_url_file=mst_pvt_shellurl(mst_getrunvars('shell'), $filename,$url_vars);
    }else{
        // Неопознанный путь разрешаем от корня сайта
        $MT_mod_url_file=mst_getwwwpath('root').$filename;
        $MT_mod_url_file=mst_util_addurlvar($MT_mod_url_file,$url_vars);
    }

    return $MT_mod_url_file;
}
/**
 * Выделяет из абсолютного пути имя модуля и путь внутри модуля 
 * (существование модуля не проверяется)
 * @param $syspath
 * @return mixed boolean or array
 */
function mst_modpath_parse($syspath)
{
	// Возвращает путь внутри модуля
	$result = array();
	// Преобразуем путь в абсолютный
	$syspath = realpath($syspath);
	if (!$syspath OR !file_exists($syspath))
	{
		//
		mst_error('Неправильный путь',
                    "Путь {$syspath} не указывает на существующий файл или папку",1);
		return false;
	}
	// Путь к папке с модулями
	$modspaths = mst_pvt_getincmoddirs();
	// Получаем путь к модулю
	// $MT_mod_path = mst_pvt_modpath($MT_mod_name,null,false,false);
	// Проверим, не выходит ли путь за границы папки с модулями
	$path_ok = false;
	foreach ($modspaths as $modspath)
	{
		$modspath = realpath($modspath).'/';
		$modpath_len = strlen($modspath);
		if (strncmp($syspath , $modspath, $modpath_len) == 0)
		{
			$path_ok = true;
			break;
		}
	}
	if ($path_ok!==true)
	{	// Ни в одной папке расширений модулель не был найден
		mst_error('Неправильный путь',
	                    "Путь {$syspath} выходит за пределы папки с модулем",1);
		return false;
	}
	// Вычисляем путь внутри папки модулей
	$modsyspath = substr($syspath,$modpath_len);
	if (strlen($modsyspath)<1)
	{
		//
		mst_error('Неправильный путь',
                    "Путь {$syspath} не принадлежит модулю",1);
		return false;
	}
	// Ищем слеш, разделяющий имя модуля и путь
	$slash_pos = strpos($modsyspath, '/');
	// Имя модуля
	if ($slash_pos)
	{
		// В пути не только имя модуля
		$result['MT_mod_name'] = substr($modsyspath,0,$slash_pos);
		// Путь, внутри модуля
		$result['path'] = substr($modsyspath,$slash_pos+1);
		// Ищем последний слеш
		$slash2_pos = strrpos($result['path'], '/');
		if ($slash2_pos)
		{
			// В пути есть слеши
			$result['file'] = substr($result['path'],$slash2_pos+1);
			$result['dir'] = substr($result['path'],0,$slash2_pos+1);
		}else
		{
			// Слешей в пути нет
			$result['file'] = $result['path'];
		}


	}else
	{
		// В пути только имя модуля
		$result['MT_mod_name'] = $modsyspath;
	}
	return $result;
}
/**
 * Возвращает разобранный в массив путь к файлу, из которого была вызвана
 * @param $disp
 * @return mixed boolean or array
 */
function mst_modpath_parsethis($disp=0)
{
	// Возвращает разобранный в массив путь к файлу, из которого была вызвана
	$backtrace=debug_backtrace();
	return mst_modpath_parse($backtrace[$disp]['file']);
}
function mst_modmkdatadir($MT_mod_name,$path,$recursive=true,$exist_ok=false)
{
	//
	if ('dat/'!=substr($path,0,4))
	{
		//
		mst_error('Неправильный путь',
                    "Директория ({$path}) в модуле ({$MT_mod_name}) не располагается в директории данных",1);
		return false;
	}
	$syspath = mst_modpath($MT_mod_name,$path,false,true);
	if (!$syspath)
	{
		//
		mst_error('Неправильный путь',
                    "Неправильный путь ({$path}) в модуле ({$MT_mod_name})",1);
		return false;
	}
	return mst_pvt_mkdir($syspath,$recursive,$exist_ok);
}
/**
 * @return номер_начальной_строки
 * @param mst-путь $filename
 * @param массив_доп_переменных $url_vars
 * @param имя_переменной_счетчик(необ) $varname
 * @param всего_строк $allnums
 * @param строк_на_странице $limit
 * @param показывать_указатель $show
 * @desc Вычисляет номер начальной строки при постраничном выводе списоков и выводит счетчик
*/
function mst_ppagesurl($filename=null,$url_vars=NULL,$varname='npages',$allnums,$limit,$show=TRUE,$max_onnav=10)
{   // Возвращает URL
    if(is_null($filename)){$filename='THIS';}
    // Всего страниц
    $pages=floor(($allnums-1)/$limit);
    // Определяем номер текущей страницы
    if(isset($_GET[$varname]) and strval($_GET[$varname])!='')
    { // Если номер страницы задан
      $thispage=intval($_GET[$varname]);
    }else{ // Если номер страницы не задан
      $thispage=$pages;
    }
    // Выводим указатель страниц
    if($show)
    {
        if($pages>$max_onnav) 
        {
            if(($pages-$thispage)<($max_onnav/2))
            {
                $fr=$pages;
                $to=$pages-$max_onnav;
            }
            elseif(($pages-$thispage)>($pages-$max_onnav/2))
            {
               $fr=$max_onnav;
               $to=0;
            }
            else 
            {
                $offs=$pages-$thispage;
                $fr=$pages-$offs+$max_onnav/2;
                $to=$fr-$max_onnav;       
            }
        }
        else
        {
            $fr=$pages;
            $to=0;   
        }
            
        ?><span class="mst_cntlist">Пролистать:</span><?
        //for($page=$pages;$page>=0;--$page)
        for($page=$fr;$page>=$to;--$page)
        {   // От нулевой страницы до последней
            // Подсчет номеров первого и последнего блоков
            // на странице для указателя
            $b_page=($pages-$page)*$limit+1; // номер первого блока на странице
            if(($pages-$page+1)*$limit<$allnums)
            {   // Если не дошли до последнего блока
                $end_page=($pages-$page)*$limit+$limit;
            }else{ // если дошли до последнего блока
                $end_page=$allnums;
            } // номер последнего блока на странице

            // Отображение указателя
            if($page==$thispage)
            {   // если текущая страница
                ?> <span class="mst_cntlist"><? echo $b_page; ?>-<? echo $end_page; ?></span> <?
            }else{ // не текущая страница
            	$url_vars[$varname]=$page;
                ?><a href="<?=mst_url($filename,$url_vars)?>" class="mstcnt_list_lnk"><?="{$b_page}-{$end_page}"?></a>
                <?
            }

        }
    }
    // Конец указателя страниц

    // Номер начальной строки
    return intval(($pages-$thispage)*$limit);
}

// ************************************
// Работа с библиотеками
// ************************************
function mst_initlib($MT_lib_name,$libver=NULL)
{
	// Подключение библиотеки $libname, с весией не менее $libver
	global $MT_libs;
	$libpath=mst_getpath('lib').$MT_lib_name.'.php';

	if (empty($MT_lib_name))
	{
		return false;
	}

	// Проверим на существование
	if (!file_exists($libpath))
	{
	    mst_error('Библиотека не найдена',
		    "Библиотека {$MT_lib_name} не найдена ($libpath)");
		return false;
	}

	if (isset($MT_libs[$MT_lib_name]['ver']))
	{   // Библиотека уже подключена
		return false;
	}

    // *********
    // Инициализируем библиотеку
    // Если библиотека еще не подключена - подключаем

    include_once($libpath);
    // Запоминаем номер версии
    $MT_libs[$MT_lib_name]['ver']=$MT_lib_ver;

    // *********

	// Проверяем список переменных на установленость в библиотеке
	// $varlist=array('MT_mod_name','MT_mod_ver');
    // Пока не все библиотеки подгружаются через init проверку отменяем
    $varlist=array('MT_lib_ver');
	foreach($varlist as $var)
	{
		if (empty($$var))
		{
		    mst_error('Переменная не определена',
		    "В библиотеке {$MT_lib_name} не определена переменная \$$var ($libpath)");
			return false;
		}
	}

	/*
	// Проверка на тип
	if ('lib'!=$MT_mod_type)
	{
		user_error("Подключенный файл $libpath не является библиотекой",E_USER_WARNING);
		return false;
	}
	*/

	// Если затребованная библиотека старшей версии чем существующая
	if (!is_null($libver) && $libver > $MT_lib_ver)
	{
	    mst_error('Библиотека устарела',"Требуемая библиотека {$MT_lib_name} устарела");
		return false;
	}

	return true;
}


// ************************************
// Работа с модулями
// ************************************

function &mst_getmodenv($MT_mod_name)
{   // Получить окружение модуля
    global $MT_mods;
    $vars['MT_mod_name']=$MT_mod_name;
    $vars['MT_mod_ver']=$MT_mods[$MT_mod_name]['ver'];
    // Обнуляем переменные, инициализируемые в файле модуля
    $vars['MT_mod_returnvars']=NULL;
    // Добавляем ссылки на данные модуля
    $vars['MT_mod_cfg']=$MT_mods[$MT_mod_name]['cfg'];

    return $vars;
}
function mst_savemodvenv($MT_mod_name,$vars)
{   // Сохранить окружение модуля
    // Эта функция только для внутреннего использования
    mst_acces_onlyfromthisfile();
}
function &mst_getdatemod($MT_mod_name,$var)
{   // Получить данные модуля
    global $MT_mods;
    if ($MT_mods[$MT_mod_name]['ver'])
    {
        return $MT_mods[$MT_mod_name]['dat'][$var];
    }
    else
    {
        mst_error('Модуль не инициализирован',
                "Модуль {$MT_mod_name} не инициализирован");
        return	NULL;
    }
}
function mst_setdatemod($MT_mod_name,$var,$date)
{   // Установить данные модуля
    global $MT_mods;
    if ($MT_mods[$MT_mod_name]['ver'])
    {
        return $MT_mods[$MT_mod_name]['dat'][$var]=$date;
    }
    else
    {
        mst_error('Модуль не инициализирован',
                "Модуль {$MT_mod_name} не инициализирован");
        return;
    }
}
function mst_getcfgmod($MT_mod_name,$var)
{   // Получить настройки модуля
    global $MT_mods;
    if ($MT_mods[$MT_mod_name]['ver'])
    {
        return $MT_mods[$MT_mod_name]['cfg'][$var];
    }
    else
    {
        mst_error('Модуль не инициализирован',
                "Модуль {$MT_mod_name} не инициализирован");
        return;
    }
}
function mst_getinfomod($MT_mod_name,$var)
{   // Получить настройки модуля
    global $MT_mods;
    if ($MT_mods[$MT_mod_name]['ver'])
    {
        return $MT_mods[$MT_mod_name]['info'][$var];
    }
    else
    {
        mst_error('Модуль не инициализирован',
                "Модуль {$MT_mod_name} не инициализирован");
        return;
    }
}


function mst_loadinfomod($MT_mod_name)
{   // Загрузить информацию о модуле
    // Проверяем, правильно ли переданы параметры
    if (!mst_pvt_modtestexec($MT_mod_name))
    {
        return false;
    }

    // Получаем путь к модулю
    $MT_mod_path=mst_pvt_modpath($MT_mod_name);
    if(!$MT_mod_path){return false;}
    $MT_mod_path_info=mst_pvt_modpath($MT_mod_name,'modinfo.php',true);
    if(!$MT_mod_path_info)
	{
		//
		mst_error('Отсутствует modinfo.php',
                "Файл описания модуля ({$MT_mod_name}) отсутствует",2);
		return false;
	}

    include($MT_mod_path_info);

	// Проверяем список переменных на установленость в modinfo.php
	$varlist=array('ver');
	foreach($varlist as $var)
	{
		if (empty($MT_mod_info[$var]))
		{
		    mst_error('Переменная не определена',
                "В файле описания модуля {$MT_mod_name} не определена переменная \$$var ({$MT_mod_path_info})",2);
			return false;
		}
	}
    return $MT_mod_info;

}

// Инициализация модуля
function mst_initmod($MT_mod_name,$MT_mod_ver_req=NULL)
{
    // Проверяем, можно ли инициализировать модуль с такими параметрами
    if (!mst_pvt_modtestexec($MT_mod_name,'init.php',true))
    {
        return false;
    }
    // Проверяем, существует ли модуль
    if (!mst_pvt_modpath($MT_mod_name))
    {
        return false;
    }
    
    // Подключение модуля $modname, с версией не менее $modver
    global $MT_core_path,$MT_mods;

    // Проверяем , подключен ли модуль
    if (isset($MT_mods[$MT_mod_name]['ver']))
    {   // Модуль уже подключен
        if(!empty($MT_mod_ver_req) OR $MT_mods[$MT_mod_name]['ver']>=$MT_mod_ver_req)
		{
			return true;
		}else
		{
			mst_error('Модуль устарел',
                    "Установленный модуль ({$MT_mod_name}) старше версии ({$MT_mod_ver_req})",1);
			return false;
		}
    }

    // Получаем информацию о модуле
    $MT_mod_info=mst_loadinfomod($MT_mod_name);


    // Проверяем , загружена ли информация о модуле
    if (empty($MT_mod_info))
    {   // Модуль не найден
        return false;
    }
    // Обрабатываем загруженную информацию
    $MT_mod_ver=$MT_mod_info['ver'];
    if (!is_null($MT_mod_ver_req) AND $MT_mod_ver_req > $MT_mod_ver)
    {   // Если затребованный модуль старшей версии чем существующий
        mst_error('Модуль устарел',
                    "Установленный модуль {$MT_mod_name} устарел");
        return false;
    }

    // Получаем путь к модулю
    $MT_mod_path=mst_modpath($MT_mod_name);
    $MT_mod_path_init=mst_pvt_modpath($MT_mod_name,'init.php');
    if(!$MT_mod_path_init)
    {   // Нет файла инициализации
        return false;
    }


    // *********
    // Инициализируем модуль
    include_once($MT_mod_path_init);
    // Запоминаем номер версии
    $MT_mods[$MT_mod_name]['ver']=$MT_mod_ver;
    //  Запоминаем информацию о модуле
    $MT_mods[$MT_mod_name]['info']=$MT_mod_info;
    // Запомним глобальные переменные
    $MT_mods[$MT_mod_name]['globalvars']=@$MT_mod_globalvars;
    // Запомним переменные окружения
    $MT_mods[$MT_mod_name]['envvars']=@$MT_mod_envvars;    
    //  Запоминаем параметры модуля
    $MT_mods[$MT_mod_name]['cfg']=@$MT_mod_cfg;
    //  Запоминаем данные модуля
    $MT_mods[$MT_mod_name]['dat']=@$MT_mod_dat;

    // *********

    /* Теперь не исползуется
    // Проверяем список переменных на установленость в модуле
	$varlist=array('MT_mod_ver');
	foreach($varlist as $var)
	{
		if (empty($$var))
		{
			user_error("В модуле {$MT_mod_name} не определена переменная \$$var ({$MT_mod_path_init})",E_USER_WARNING);
			return false;
		}
	}
    */

	// Если есть - установим глобальные переменные
	if (!empty($MT_mod_globalvars))
	{
		$globals=explode(',',$MT_mod_globalvars);

        foreach($globals as $g)
		{
            $g=trim($g);
            $GLOBALS[$g]=$$g;
        }

	}

	return true;
}

function mst_modload($MT_mod_name,$MT_mod_cust=NULL)
{   // Загрузить модуль
    // Проверяем, можно ли инициализировать модуль с такими параметрами
    if (!mst_pvt_modtestexec($MT_mod_name,'load.php',true))
    {
        return false;
    }
    return mst_modfileload($MT_mod_name,'load.php',$MT_mod_cust);
}

/**
 * @return массив_возвр_значений
 * @param имя_модуля $MT_mod_name
 * @param путь_внутри_модуля $MT_mod_file
 * @param перелаваемые_параметры $MT_mod_cust
 * @param один_раз? $MT_mod_once
 * @desc Загрузить файл из модуля. При необходимости модуль инициализируется
*/
function mst_modfileload($MT_mod_name,$MT_mod_file,$MT_mod_cust=NULL,$MT_mod_once=false,$MT_mod_initonly=false)
{   // Загрузить модуль
    // Проверяем, можно ли инициализировать модуль с такими параметрами
    if (!mst_pvt_modtestexec($MT_mod_name,$MT_mod_file,true))
    {
        return false;
    }

    if (!$MT_mod_initonly)
    {   // Затребована не только загрузка файла
        global $MT_mods;
        // Проверяем, инициализирован ли модуль
	   if (empty($MT_mods[$MT_mod_name]['ver']))
	   {   // Если нет - инициализируем
            if(!mst_initmod($MT_mod_name))
            {   // Инициализация не произошла
                return false;
            }
	   }
        // Извлекаем окружение модуля
        extract(mst_getmodenv($MT_mod_name));    
	   if (is_array($MT_mods[$MT_mod_name]['dat']))
        {	// Если необходимо, устанавливаем ссылку на $MT_mod_dat    	
		  $MT_mod_dat=&$MT_mods[$MT_mod_name]['dat'];
        }
	   if (!empty($MT_mods[$MT_mod_name]['envvars']))
        {	// Если необходимо, регистрируем переменные из MT_mod_dat
            // как переменные окружения
            // $MT_mod_dat=&$MT_mods[$MT_mod_name]['dat'];
            $msttmp_envvars=explode(',',$MT_mods[$MT_mod_name]['envvars']);
            foreach($msttmp_envvars as $msttmp_e)
            {	// Регистрируем в текущем окружении перечисленные в envvars переменные из $MT_mod_dat
                $msttmp_e=trim($msttmp_e);
                $$msttmp_e=&$MT_mods[$MT_mod_name]['dat'][$msttmp_e];
            }
            // Уничтожаем временные переменные
            unset($msttmp_e);unset($msttmp_envvars);
        }
    }
    
    // Путь к загружаемому файлу
    $MT_mod_path_load=mst_pvt_modpath($MT_mod_name,$MT_mod_file);
	if (!$MT_mod_path_load)
	{   // Проверка, существует ли путь к загружаемому файлу
        return false;
	}

    if($MT_mod_once)
    {   // Затребовано единоразовое подключение
        include_once $MT_mod_path_load;
    }else
    {   // Затребовано обычное подключение
        include $MT_mod_path_load;
    }

    // Если затребован возврат переменных
	if (!empty($MT_mod_returnvars))
	{
		$returns=explode(',',$MT_mod_returnvars);
        foreach($returns as $r)
		{
            $g=trim($r);
            $res[$g]=$$r;

        }
        return $res;

	}
}
function mst_modlist()
{   // Списко обнаруженных модулей
	$dirs=mst_pvt_getincmoddirs();
	$res = array();
	foreach($dirs as $dir)
	{
		// Читаем содержимое папки
		$odir = opendir($dir);
		while (($filename = readdir($odir)) != false)
		{
			// echo "<br>{$dir} {$filename}";
		    if (
					'.'===$filename{0}
					// Отсекаем служебные файлы CVS и Subversion
	                OR 'CVS'==$filename
					// Модулем считается только папка
	                OR !is_dir($dir.$filename)
					// Считаем только один раз
					OR in_array($filename,$res)
	            )
		    {  // Это не модуль
		        continue;
		    }
		    // Это - модуль
		    $res[]=$filename;
		}
	}
	sort($res);
	return $res;
}

function mst_modexists($MT_mod_name)
{
    return mst_pvt_modpath($MT_mod_name,null,TRUE,FALSE) !==false;
}
// *******************************************
// Закрытые методы для работы с модулями

/**
 * @return путь
 * @param имя_модуля $MT_mod_name
 * @param путь_внутри_модуля $filename
 * @param не_ругаться_на_ошибку $non_error
 * @desc Возвращает физический путь к модулю или файлу модуля 
 * @desc ($filename может содержать относительный путь только для существующих файлов)
*/
function mst_pvt_modpath($MT_mod_name,$filename=null,$non_error=FALSE,$non_exists=false)
{   // Возвращает путь к модулю
    // Если путь не правильный - возвращаем false
    // Вывод ошибок настроен на вызов модуля из других функций my-site
    // Эта функция только для внутреннего использования
    mst_acces_onlyfromthisfile();
    
	global $MT_core_path;
	if (!mst_pvt_modtestexec($MT_mod_name,$filename,false,false))
	{  // Модуль вызван с неправильными параметрами
	    return false;
	}

	$mod_dirs=mst_pvt_getincmoddirs();
	$mod_exist = false;
	foreach($mod_dirs as $mod_dir)
	{
		// Ищем модуль в разных папках
		$MT_mod_path=$mod_dir.$MT_mod_name.'/';
		if (is_dir($MT_mod_path))
		{
			//
			$mod_exist = true;
			break;
		}
	}
	if (!$mod_exist)
	{
		// Модуля нет и в папке расширений
		if(!$non_error)
		{
			mst_error('Модуль не найден',
                "Модуль {$MT_mod_name} не найден ($MT_mod_path)",2);
		}
		return false;
	}
    if(empty($filename))
    {   // Запрошен путь к модулю
        return realpath($MT_mod_path);
    }
	// Задаем базовый путь, из которого не должен выходить путь внутри модуля
	$basepath = $MT_mod_path;
	
    // Запрошен путь внутри модуля
    if('tml/'==substr($filename,0,4))
    {   // Запрошен шаблон
		// Переопределяем базовый путь
        $MT_mod_path_file=mst_getpath('tml').mst_getconfig('themes').
                        "/{$MT_mod_name}/".substr($filename,4);
        if(file_exists($MT_mod_path_file))
        {   // Файл в теме есть, возвращаем путь
			// Переопределяем базовый путь
			$basepath = mst_getpath('tml').mst_getconfig('themes').
                        "/{$MT_mod_name}/";
            // return $MT_mod_path_file;
        }else
		{
        	// Файла в теме нет, берем путь в модуле
			$MT_mod_path_file=$MT_mod_path.$filename;
		}
		
    }elseif('cfg/'==substr($filename,0,4))
    {   // Запрошен шаблон
        $MT_mod_path_file=mst_getpath('modscfg').
                        "{$MT_mod_name}/".substr($filename,4);
        if(file_exists($MT_mod_path_file))
        {   // Файл конфигурации существует, возвращаем путь
			// Переопределяем базовый путь
			$basepath = mst_getpath('modscfg')."{$MT_mod_name}/";
            // return $MT_mod_path_file;
        }else
		{
        	// Файла в теме нет, берем путь в модуле
			$MT_mod_path_file=$MT_mod_path.$filename;
		}
    }elseif('dat/'==substr($filename,0,4))
    {   // Запрошен файл внутри папки с данными модулей
    	// Переопределяем базовый путь
		$basepath = mst_getpath('moddata')."{$MT_mod_name}/";
		if (!is_dir($basepath))
		{
			// Путь отсутствует
			$basepath = mst_getpath('moddata');
		}
        $MT_mod_path_file=mst_getpath('moddata').
                        "{$MT_mod_name}/".substr($filename,4);
    }else{
        $MT_mod_path_file=$MT_mod_path.$filename;
    }

	// Переводим путь в абсолютный вид
	$basepath_old = $basepath;
	$basepath = realpath($basepath);
	if (!$basepath OR !file_exists($basepath))
	{
		// Базовый путь не существует
		if(!$non_error)
        {
			mst_error('Неправильный путь',
                    "Базовый путь ({$basepath_old}) для пути ({$filename}) в модуле "
						."({$MT_mod_name}) не существует",2);
        }
		return false;
	}
	// Проверим, не выходит ли путь за границы допустимых папок
	if ($non_exists)
	{
		// Пути к несуществующим файлам разрешены
		// Тогда запрещены относительные пути внутри модуля
		if (!mst_util_norelative($MT_mod_path_file))
		{
			//
			if(!$non_error)
			{
				mst_error('Неправильный путь',
                    "Относительные ссылки пути разрешены только для существующих файлов"
                         ." ({$MT_mod_path_file})",2);
			}
			return false;
		}
	}else
	{
		// Пути к несуществующим файлам запрещены
		// Преобразуем путь в абсолютный
		$MT_mod_path_file = realpath($MT_mod_path_file);
		// Проверям, существует ли файл (иначе realpath возвращает false)
		if (!$MT_mod_path_file OR !file_exists($MT_mod_path_file))
		{
			// Файл не найден
			if(!$non_error)
			{
				mst_error('Файл не найден',
					"Путь ({$filename}) в модуле ({$MT_mod_name}) не найден",2);
			}
			return false;
		}
		// Проверяем, попадает ли файл в разрешенную область
		if (strncmp ($MT_mod_path_file , $basepath, strlen($basepath))!=0)
		{
			//
			if(!$non_error)
			{
				mst_error('Неправильный путь',
                    "Путь в модуле {$MT_mod_name} выходит за пределы модуля"
                         ." ({$MT_mod_path_file})",2);
			}
			return false;
		}
	}
	// Добавляем конечный слеш, если он был, а сейчас нет
	if ('/'===substr($filename,-1) AND '/'!==substr($MT_mod_path_file,-1))
	{
		$MT_mod_path_file .= '/';
	}
    return $MT_mod_path_file;
}

function mst_pvt_modtestexec($MT_mod_name,$MT_mod_file=null,$need_file=false,$die=false)
{   // Проверяем правильность вызова модуля
    // Эта функция только для внутреннего использования
    mst_acces_onlyfromthisfile();
    $error = false;
    // Передано ли имя модуля
	if (empty($MT_mod_name))
	{   // Проверка, передано ли имя модуля
        mst_error('Не перадано имя модуля','',2);
        $error = true;
	}
    // Передано ли имя файла
    if (empty($MT_mod_file) AND $need_file)
	{   // Проверка, задано ли имя файла
        mst_error('Не перадано имя файла','',2);
        $error = true;
	}
	if (!mst_util_checkmodname($MT_mod_name,false,false))
	{   // Проверка, задано ли имя модуля
        mst_error('Неправильное имя модуля',"Имя модуля '{$MT_mod_name}' содержит недопустимые символы",2);
        $error = true;
	}

	if ($error)
	{
        if ($die)
        {   // Завершаем работу
            die('<br />Неправильный вызов модуля');
        }
        return false;
	}
    return true;
}

/**
 * @return URL
 * @param модуль-shell $MT_mod_name
 * @param остаток_mst-пути $filename
 * @param массив_доп_переменных $url_vars
 * @desc Возвращает URL внутри shell по mst-пути
*/
function mst_pvt_shellurl($MT_mod_name,$filename=null,$url_vars=NULL)
{   // Возвращает url внутри shell
    // Эта функция только для внутреннего использования
    mst_acces_onlyfromthisfile();
    // Проверяем, правильно ли переданы параметры
    if (!mst_pvt_modtestexec($MT_mod_name))
    {
        return false;
    }
    // Ищем функцию разрешения ссылок
    if(!function_exists($MT_mod_name.'_shell_url'))
    {   // Функция не обьявлена
        if(!mst_initmod($MT_mod_name)
            or !function_exists($MT_mod_name.'_shell_url'))
        {   // Инициализация не произошла
            // Инициализация произошла, но функция не найдена
            mst_error('Модуль не найден',
                "URL не может быть разрешен,"
                ."так как модуль {$MT_mod_name} не найден "
                ."или не содержит функцию {$MT_mod_name}_shell_url()",3);
            return false;
        }

    }
    // Функция есть, вызываем
    $filename_shell=call_user_func($MT_mod_name.'_shell_url', $filename);


    $MT_mod_url_file=mst_pvt_shellbaseurl($MT_mod_name).$filename_shell;
    $MT_mod_url_file=mst_util_addurlvar($MT_mod_url_file,$url_vars);
    return $MT_mod_url_file;
}
function mst_pvt_shellbaseurl($MT_mod_name)
{	// Возвращает базовый URL shell
    // Эта функция только для внутреннего использования
    mst_acces_onlyfromthisfile();
    // Проверяем, правильно ли переданы параметры
    if (!mst_pvt_modtestexec($MT_mod_name))
    {
        return false;
    }
    
    // Получаем массив c переопределениями базовых url различных shell
	$shellbase=mst_getwwwpath('shellbase');
	
	if(mst_getrunvars('cshell_url') AND mst_getrunvars('shell')==$MT_mod_name)
	{	// Задан базовый url для текущей shell в параметрах точки входа
		$baseurl=mst_getrunvars('cshell_url');
	}elseif(isset($shellbase[$MT_mod_name]))
	{	// Базовый url shell задан в конфигурационном файле
		$baseurl=$shellbase[$MT_mod_name];
	}else
	{	// Переопределения не заданы, генерируем базовый url по умолчанию
		$baseurl=mst_getwwwpath('shell')."{$MT_mod_name}/";
	}
	return $baseurl;
}
function mst_pvt_mkdir($syspath,$recursive=true,$exist_ok=false)
{
	// Создать директорию
	if (!$syspath)
	{
		//
		mst_error('Неправильный путь',
                    "Директория ({$syspath}) не может быть создана",2);
		return false;
	}
	if (file_exists($syspath))
	{
		//
		if ($exist_ok)
		{
			return true;
		}
		mst_error('Файл существует',
                    "Директория ({$syspath}) не может быть создана",2);
		return false;
	}
	// Создаем директорию
	if (!mkdir($syspath,mst_getconfig('www_dirmod'),$recursive))
	{	// 
		// Ошибка при создании директории
		mst_error('Ошибка создания директории',
                    "Ошибка при создании директории ({$syspath})",2);
		return false;
	}
	if (mst_getconfig('www_group'))
	{
		if (!chgrp($syspath,mst_getconfig('www_group')))
		{
			// Ошибка изменения группы
			mst_error('Ошибка изменения группы',
                    "Не могу установить группу ("
                    .mst_getconfig('www_group')
					.") для директории ({$syspath})",2);
			return false;
		}
	}
	if (mst_getconfig('www_user'))
	{
		if (!chgrp($syspath,mst_getconfig('www_user')))
		{
			// Ошибка изменения владельца
			mst_error('Ошибка изменения владельца',
                    "Не могу установить владельца ("
                    .mst_getconfig('www_user')
					.") для директории ({$syspath})",2);
			return false;
		}
	}
	return true;
}
/**
 * Возвращает массив путей к папкам с модулями
 * @return array
 */
function mst_pvt_getincmoddirs()
{
	
	mst_acces_onlyfromthisfile();
	//
	$arr = array(mst_getpath('mod'));
	$ext = mst_getpath('modext');
	if (is_string($ext))
	{
	    $ext = array($ext);
	}
	$arr = array_merge($arr,$ext);
	return $arr;
}

// ************************************
// Дополнительные функции
// ************************************
/**
 * Выводим сообщение об ошибке и пишем ошибку в лог
 *
 * @param string $error_name
 * @param string $error_about
 * @param int $level
 */
function mst_error($error_name,$error_about='',$level=1,$exeption=false)
{
    // $error_name - название ошибки
    // $level - уровень источника ошибки
    // Получаем информацию трассировки
    $backtrace=debug_backtrace();
    if(isset($backtrace[1]))
    {
        // Пишем ошибку в лог
        error_log(date('d-m-Y H:i:s')
                        ."\t{$error_name}"
                        ."\t{$backtrace[$level]['function']}"
                        ."\t{$backtrace[$level]['line']}"
                        ."\t{$backtrace[$level]['file']}"
                        ."\t{$error_about}"
                        ."\t{$_SERVER['REMOTE_ADDR']}"
                        ."\n"
                    ,3,mst_getpath('log'));
        if(mst_is_debug())
        {   // Отладка включена - показываем ошибку на экране
            //
            echo '<h2 style="color:red">Ошибка</h2>';
            echo "Вызов метода <b>{$backtrace[$level]['function']}()</b>";
            echo "<br />в строке <b>{$backtrace[$level]['line']}</b>";
            echo "<br />файла <b>{$backtrace[$level]['file']}</b>";
            echo "<br />привел к ошибке:";
            echo " <b>{$error_name}</b><br />{$error_about}";
            // echo '<pre>';
            // print_r($backtrace);
            // echo '<pre>';
        }
        if ($exeption)
        {
            // Выбрасываем исключение
            throw new Exception($error_name);
        }
    }
}
function  mst_acces_onlyfromthisfile()
{   // Умираем с ошибкой, если функция вызвана не из того же файла, в котором определена
    // Получаем историю вызовов
    $backtrace=debug_backtrace();
    if (realpath($backtrace[1]['file'])!=realpath($backtrace[0]['file']))
    {
        mst_error('Несанкционированный вызов',"Функцию {$backtrace[1]['function']}() можно вызывать только из файла {$backtrace[0]['file']}",2);
        die('<br />Несанкционированный вызов');
    }
}

// 
// ********************************************************
// Проверка условий
function mst_is_debug()
{
    return mst_getconfig('debug')=='enable';
}

// 
// ********************************************************
// Утилиты
function mst_util_addurlvar($url,$url_vars=NULL)
{   // Перевести массив в строку URL
    if(empty($url_vars)){return $url;}
    $url_str='';
    foreach($url_vars as $key=>$val)
    {   // Просматриваем массив
        if(!is_scalar($val)) continue;
        if($url_str){$url_str=$url_str.'&';}
        $url_str=$url_str.$key.'='.urlencode($val);
    }
    if(strrpos ($url,'?'))
    {
        $url_str=$url.'&'.$url_str;
    }else{
        $url_str=$url.'?'.$url_str;
    }
    return $url_str;
}
function mst_util_checkmodname($MT_mod_name,$generror=false,$die=false)
{   // Проверить имя модуля на правильность
    if (ereg('^[a-z0-9_\-]+$',$MT_mod_name) AND strlen($MT_mod_name)>0 AND strlen($MT_mod_name)<=30)
    {
        return true;
    }
    if ($generror)
    {
        mst_error('Неправильное имя модуля',"Имя модуля '{$MT_mod_name}' содержит недопустимые символы",2);
    }
    if ($die)
    {
        die('<br />Неправильное имя модуля');
    }
    return false;
}
function mst_util_norelative($path)
{   // Проверить путь на содержание относительных переходов
	if (strpos($path,'./')===false)
	{
		// Относительных ссылок нет
		return true;
	}else{
		// Относительные ссылки есть
		return false;
	}
}
function mst_util_nodirs($filename)
{   // Проверить имя файла на наличие обращений к директориям
	if (ereg('^[^./][^/]*$', $filename))
	{
		// Имя содержит относительные переходы
		return true;
	}else
	{
		return false;	
	}
}
// ********************************************************
?>
